#include <iostream>
#include <functional>
#include <algorithm>
#include <vector>

using namespace std;
using namespace std::placeholders;

struct Foo
{
    int a, b;
};

template <typename T>
void type_traits_output(const T& )
{
    cout <<"\n type: " << typeid(T).name() << endl;
    cout <<"is_void \t" << is_void<T>::value << endl;
    cout << "is_array \t " << is_array<T>::value << endl;

    cout <<"is_class \t" << is_class<T>::value << endl;

    cout <<"is_point \t" << is_pointer<T>::value << endl;

    cout << "is_object \t" << is_object<T>::value << endl;

    cout <<"is_function \t" << is_function<T>::value << endl;
}

double my_divide(double x, double y) { return x / y;}

int main()
{
    auto fn_five = bind(my_divide, 10,2);
    cout << fn_five() << '\n';

    auto fn_half = bind(my_divide, _1, 2);//通过_1 来占位 第一参数
    cout << fn_half(10) <<'\n';//在使用是，传递一个参数，这个参数即为_1的object

    //同上面相同
    auto fn_invert = bind(my_divide, _2, _1);//位置还可以进行调整
    cout << fn_invert(10, 2) << '\n';//其实 arg1 为2， arg2 为10

    auto fn_rounding = bind<int>(my_divide, _1, _2);//还能插入一个模板，且绑定到返回值类型。默认为原函数的return type
    cout << fn_rounding(10, 3) <<'\n';

    cout <<"--------------" << '\n';


    //找到一个简便的使用方式
    vector<int> v {51,52,40,20,70,20,59};

    auto fn = bind(less<int>(), _1, 50);
    cout << count_if(v.cbegin(), v.cend(), fn) << endl;

    cout << count_if(v.begin(), v.end(), bind(less<int>(), _1, 50)) << endl;

    cout << count_if(v.cbegin(), v.cend(), bind2nd(less<int>(), 50)) << endl;

    type_traits_output<vector<int> >(v);

    array<int,5> arr;
    type_traits_output<array<int,5 >>(arr);

    void * p = NULL;
    type_traits_output<void*>(p);


    type_traits_output<Foo>(Foo());


    Foo pair{1,2};
    auto memdata = bind(&Foo::a, pair);
    cout << memdata() << endl;
    return 0;
}
